package com.guava;

import com.google.common.base.Function;
import com.google.common.collect.*;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Ints;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * OrderingAdvanceTester--GuavaTest
 * 排序进阶
 *
 * @author: Jovi
 * @createTime: 2018-05-07 16:13
 **/
public class OrderingAdvanceTester {

    private static Ordering<City> flexOrdering = new Ordering<City>() {

        /* 链式条件组装 */
        @Override
        public int compare(City c1, City c2) {
            return ComparisonChain.start().compare(c1.getAverageRainfall(), c2.getAverageRainfall(), Ordering.<Double>natural())
                    .compare(c1.getPopulation(), c2.getPopulation(), Ordering.<Integer>natural().reverse()).result();
        }
    };


    public static void main(String[] args) {

        CityBypopulation cityBypopulation = new CityBypopulation();
        CityByRainfall cityByRainfall = new CityByRainfall();
        City.CityBuilder cityBuilder = new City.CityBuilder();

        City c1 = cityBuilder.population(1000).averageRainfall(43.1).date("2017年05月08日").name("sh").build();
        City c2 = cityBuilder.population(1000).averageRainfall(22.1).date("2018年05月08日").name("sh").build();
        City c3 = cityBuilder.population(4000).averageRainfall(10.1).date("2019年05月08日").name("sh").build();

        City c4 = cityBuilder.population(7000).averageRainfall(43.1).date("2005年05月08日").name("nj").build();
        // City c5 = cityBuilder.population(8000).averageRainfall(22.1).date("2004年05月08日").build();
        City c5 = new City(null, "2004年05月08日", 8000, 22.1);
        City c6 = cityBuilder.population(6000).averageRainfall(10.1).date("2003年05月08日").name("xz").build();

        List<City> cities = Lists.newArrayList(c1, c2, c3);
        List<City> cities2 = Lists.newArrayList(c1, c2, c3, c4, c5, c6);
        Ordering<City> oneCityOrdering = Ordering.from(cityBypopulation);
        Ordering<City> secondaryOrdering = Ordering.from(cityBypopulation).compound(cityByRainfall);

        System.out.println("单参数排序，按照流行程度从小到大排序：");
        printResult(oneCityOrdering.sortedCopy(cities));
        System.out.println("多参数排序，优先按照流行程度从小到大排序，相同流行程度再按照降水量从小到大排序：");
        printResult(secondaryOrdering.sortedCopy(cities));

        List<City> citiesChains = flexOrdering.sortedCopy(cities2);
        System.out.println("先按照降水量从小到大，再按照流行度从大到小，链式排序条件组合后队列:");
        printResult(citiesChains);


        Ordering<City> orderingOnResult = Ordering.natural().reverse().onResultOf(
                new Function<City, Comparable>() {
                    public Comparable apply(City city) {
                        return city.getAverageRainfall();
                    }
                }
        );
        System.out.println("onResultOf条件，降水量从大到小排序:");
        printResult(orderingOnResult.sortedCopy(cities2));

        System.out.println("explicit根据传入对象的顺序排序:");
        printResult(Ordering.explicit(cities2).sortedCopy(cities2));

        final DateTimeFormatter format = DateTimeFormat.forPattern("yyyy年MM月dd日");

        Ordering<City> orderingByDate = Ordering.natural().reverse().onResultOf(
                new Function<City, Comparable>() {
                    @Override
                    public Comparable apply(City city) {
                        return DateTime.parse(city.getDate(), format);
                    }
                }
        );
        System.out.println("onResultOf条件，时间从大到小排序:");
        printResult(orderingByDate.sortedCopy(cities2));

        getTransFormLists(cities2);
    }

    /**
     * 格式化，并筛选
     *
     * @param cities2
     */
    private static void getTransFormLists(List<City> cities2) {
        List<String> transform = Lists.transform(cities2, new Function<City, String>() {
            @Override
            public String apply(City city) {
                if (city.getPopulation() > 4000) {
                    return city.getName();
                } else {
                    return null;
                }
            }
        });

        System.out.println("筛选后：" + transform);
        transform.removeAll(Collections.singleton(null));


        System.out.println(transform);
        Multiset<String> sets = HashMultiset.create(transform);

        System.out.println(sets);

        String dataTypes = "";

        for (Multiset.Entry<String> entry : sets.entrySet()) {
            dataTypes += entry.getElement() + "," + entry.getCount() + ";";
        }
        System.out.println(StringUtils.substringBeforeLast(dataTypes, ";"));
    }

    private static void printResult(List<City> citiesChains) {
        for (City city : citiesChains) {
            System.out.println("流行度：" + city.getPopulation() +
                    "；降水量：" + city.getAverageRainfall() + "; 时间：" + city.getDate());

        }
    }

}


@Builder
@Data
class City {

    private String name;
    private String date;
    private int population;
    private double averageRainfall;

}

class CityBypopulation implements Comparator<City> {

    public int compare(City o1, City o2) {
        return Ints.compare(o1.getPopulation(), o2.getPopulation());
    }
}

class CityByRainfall implements Comparator<City> {
    public int compare(City o1, City o2) {
        return Doubles.compare(o1.getAverageRainfall(), o2.getAverageRainfall());
    }
}

